﻿//++
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Module Name:
//
//  EnhancedRemindersRibon.cs
//    
// Abstract:
//
//  Implements Ribbon UI's event handlers
//  
//--

using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.EnhancedReminders.Properties;
using Microsoft.Office.Interop.Outlook;
using Microsoft.Office.Tools.Ribbon;
using Microsoft.OfficeCommunicationsServer.Applications.Common;

namespace Microsoft.EnhancedReminders.OutlookAddIn
{
    /// <summary>
    /// Code behind for EnhancedRemindersRibbon
    /// </summary>
    public partial class EnhancedRemindersRibbon : OfficeRibbon
    {
        private OutlookReminderInspector _reminderInspector;
        private IExchangeSession _exchangeSession;

        /// <summary>
        /// Default constructor
        /// </summary>
        public EnhancedRemindersRibbon()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Event raised when the Enhanced Reminders Ribbon is first loaded. We initialize the
        /// properties and ComboBox items here
        /// </summary>
        /// <param name="sender">EnhancedRemindersRibbon object</param>
        /// <param name="e">RibbonUIEventArgs</param>
        private void EnhancedRemindersRibbon_Load(object sender, RibbonUIEventArgs e)
        {
            Debug.Assert(sender != null, "sender != null");
            Debug.Assert(e != null, "e != null");

            // Find OutlookReminderInspector wrapper for this appointment. 
            // If no OutlookReminderInspector wrapper is found, one will
            // be created with a ReminderItem.
            _reminderInspector = ThisAddIn.FindOutlookInspector(Context);
            Debug.Assert(_reminderInspector != null, "reminderInspector != null");

            _reminderInspector.Ribbon = sender as EnhancedRemindersRibbon;
            _exchangeSession = _reminderInspector;

            InitializeControls();
        }

        /// <summary>
        /// Returns status of connectivity
        /// </summary>
        private bool IsDisconnected
        {
            get
            {
                Debug.Assert(_exchangeSession != null, "_exchangeSession != null");
                return (_exchangeSession.ConnectionMode == OlExchangeConnectionMode.olCachedDisconnected ||
                    _exchangeSession.ConnectionMode == OlExchangeConnectionMode.olDisconnected ||
                    _exchangeSession.ConnectionMode == OlExchangeConnectionMode.olNoExchange ||
                    _exchangeSession.ConnectionMode == OlExchangeConnectionMode.olOffline ||
                    _exchangeSession.ConnectionMode == OlExchangeConnectionMode.olCachedOffline);
            }
        }

        #region Ribbon Callbacks

        /// <summary>
        /// Invoked when Time Combo is updated
        /// </summary>
        private void TimeCombo_TextChanged(object sender, RibbonControlEventArgs e)
        {
            Debug.Assert(sender != null, "sender != null");
            RibbonComboBox source = sender as RibbonComboBox;
            Debug.Assert(source != null, "source != null");

            int minutes;
            // If false is returned, user input is invalid. We won't change the previous
            // ReminderTime.
            if (ReminderOutlookUtils.TryParseRemindTime(source.Text.Trim(), out minutes))
            {
                // Set time to the ReminderItem, but do not save it.
                _reminderInspector.LeadTime = minutes;
                _reminderInspector.ReminderChanged = true;
            }

            ReminderChanged();
        }

        /// <summary>
        /// Invoked when Join Now Time Combo is updated
        /// </summary>
        private void JoinNowTimeCombo_TextChanged(object sender, RibbonControlEventArgs e)
        {
            Debug.Assert(sender != null, "sender != null");

            int minutes;
            // If false is returned, user input is invalid. We won't change the previous
            // ReminderTime.
            Debug.Assert(JoinNowTimeCombo != null, "JoinNowTimeCombo != null");
            if (ReminderOutlookUtils.TryParseRemindTime(JoinNowTimeCombo.Text.Trim(), out minutes))
            {
                // Set time to the ReminderItem, but do not save it.
                _reminderInspector.JoinNowLeadTime = minutes;
                _reminderInspector.ReminderChanged = true;
            }

            ReminderChanged();
        }

        private void ReminderChanged()
        {
            // If TryParseRemindTime fails, RefreshControls will re-set invalid user input to 
            // the previous value as stored in ReminderItem.ReminderTime
            RefreshControls();

            // This is the suggested way to set the "dirty" flag for this appointment item
            // so that user get prompted to save the changes on closing
            AppointmentItem appointment = Helpers.AssertCast<AppointmentItem>(_reminderInspector.Window.CurrentItem);
            Logger.WriteTraceInformation("Set dirty flag");
            appointment.Mileage = appointment.Mileage;

            // Known issue with VSTO: windows messages are getting processed out of order and may not 
            // refresh the control.  The workaround is to add a call to System.Windows.Forms.Application.DoEvents() to force
            // the processing of all messages currently in the message queue.
            System.Windows.Forms.Application.DoEvents();
        }

        #endregion

        #region Helpers
        /// <summary>
        /// Dynamically determine the icon for the TimeCombo
        /// </summary>
        /// <returns>ImageMso string</returns>
        private string TimeComboImageMso
        {
            get
            {
                if (IsDisconnected)
                {
                    return Resources.DisconnectedImageMso;
                }
                else
                {
                    return Resources.ConnectedImageMso;
                }
            }
        }

        /// <summary>
        /// Dynamically determine the supertip which is different for online/offline
        /// scenario
        /// </summary>
        /// <returns>Text for supertip</returns>
        private string TimeComboSupertip
        {
            get
            {
                if (IsDisconnected)
                {
                    return Resources.DisconnectedSupertip;
                }
                else
                {
                    return Resources.ConnectedSupertip;
                }
            }
        }

        /// <summary>
        /// Initialize controls
        /// </summary>
        private void InitializeControls()
        {
            Debug.Assert(_reminderInspector != null, "_reminderInspector");

            // Populate TimeComboBox items
            foreach (string time in ReminderOutlookUtils.DefaultReminderTimes)
            {
                RibbonDropDownItem item = new RibbonDropDownItem();
                item.Label = time;
                TimeCombo.Items.Add(item);

                item = new RibbonDropDownItem();
                item.Label = time;
                TimeCombo2.Items.Add(item);

                item = new RibbonDropDownItem();
                item.Label = time;
                JoinNowTimeCombo.Items.Add(item);
            }

            // We use two different ribbon groups depending on whether Join Now should
            // be available for a meeting. This means some duplication for button properties.
            // Only one ribbon group should ever be visible at a time.

            // Initializing localized labels for controls
            _ribbonGroup.Label = Resources.RibbonGroupLabel;
            _joinNowGroup.Label = Resources.RibbonGroupLabel;

            NotificationChannels.Label = Resources.RibbonChannelsButton;
            NotificationChannels2.Label = Resources.RibbonChannelsButton;
            JoinNowChannels.Label = Resources.RibbonChannelsButton;

            TimeCombo.Text = ReminderOutlookUtils.DefaultReminderTimes[0];
            TimeCombo2.Text = ReminderOutlookUtils.DefaultReminderTimes[0];
            JoinNowTimeCombo.Text = ReminderOutlookUtils.DefaultReminderTimes[0];

            _ribbonGroup.Visible = !_reminderInspector.IsJoinNow;
            _joinNowGroup.Visible = _reminderInspector.IsJoinNow;
        }

        /// <summary>
        /// Launch the Dialog Launcher Window. This is the same UI as we display in Tools->Options
        /// under the ER tab.
        /// </summary>
        private void DialogLauncherClicked(object sender, RibbonControlEventArgs e)
        {
            DialogLauncherWindow window = new DialogLauncherWindow();
            window.ShowDialog();
        }

        /// <summary>
        /// Event handler for when the "Channels" button for Join Now is clicked.
        /// </summary>
        private void JoinNowChannelsClick(object sender, RibbonControlEventArgs e)
        {
            _reminderInspector.SyncChannelsToMasterList();
            ChannelsButtonClicked(Resources.ReadOnlyChannelControlWindowJoinNowHeader, Resources.ReadOnlyChannelControlWindowJoinNowDescription, _reminderInspector.JoinNowChannels);
        }

        /// <summary>
        /// Event handler for when the "Channels" button for notifications is clicked.
        /// </summary>
        private void NotificationChannelsClick(object sender, RibbonControlEventArgs e)
        {
            _reminderInspector.SyncChannelsToMasterList();
            ChannelsButtonClicked(Resources.ReadOnlyChannelControlWindowNotificationHeader, Resources.ReadOnlyChannelControlWindowNotificationDescription, _reminderInspector.Channels);
        }

        /// <summary>
        /// Called by either of the channel buttons when they're clicked on.
        /// </summary>
        /// <param name="header">The title to use for the channels dialog</param>
        /// <param name="description">The description to use for the channels dialog</param>
        /// <param name="channels">A list of channels to use for the channels dialog</param>
        private void ChannelsButtonClicked(string header, string description, List<NotificationChannel> channels) 
        {
            ReadOnlyChannelControlWindow channelDialog = new ReadOnlyChannelControlWindow(header, description , channels);
            channelDialog.ShowDialog();

            if (channelDialog.ListChanged)
            {
                _reminderInspector.ReminderChanged = true;
                ReminderChanged();
            }
        }

        /// <summary>
        /// Refresh controls' properties
        /// </summary>
        public void RefreshControls()
        {
            // Refresh controls to update the time. This is necessary if the time entered
            // cannot be parsed, in which case we need to revert to previous value
            Debug.Assert(null != _reminderInspector, "OutlookReminderInspector is null");

            // Suspend layout to perform updates on control's properties. This prevent the VSTO runtime 
            // from calling InvalidateControl everytime we change a property. For performance reason, we want 
            // to do bulk update before we refresh the control's layout
            SuspendLayout();

            TimeCombo.Text = ReminderOutlookUtils.FormatRemindTime(_reminderInspector.LeadTime);
            TimeCombo2.Text = ReminderOutlookUtils.FormatRemindTime(_reminderInspector.LeadTime);
            JoinNowTimeCombo.Text = ReminderOutlookUtils.FormatRemindTime(_reminderInspector.JoinNowLeadTime);

            // Enabling ChannelCombo if time selected is valid
            NotificationChannels.Enabled = _reminderInspector.LeadTime != NotificationChannelListLeadTime.None;
            NotificationChannels2.Enabled = _reminderInspector.LeadTime != NotificationChannelListLeadTime.None;
            JoinNowChannels.Enabled = JoinNowChannels.Visible && _reminderInspector.JoinNowLeadTime != NotificationChannelListLeadTime.None;

            // Setting icon and supertip depending on connectivity
            TimeCombo.OfficeImageId = TimeComboImageMso;
            TimeCombo2.OfficeImageId = TimeComboImageMso;
            NotificationChannels.OfficeImageId = Resources.ChannelImageMso;
            NotificationChannels2.OfficeImageId = Resources.ChannelImageMso;
            TimeCombo.SuperTip = TimeComboSupertip;
            TimeCombo2.SuperTip = TimeComboSupertip;
            JoinNowTimeCombo.OfficeImageId = TimeComboImageMso;
            JoinNowChannels.OfficeImageId = Resources.ChannelImageMso;

            // Refresh controls' UI
            ResumeLayout();
        }

        #endregion Helper
    }
}
